package com.cndw.kungfu.model.siege.domain;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;

import com.cndw.commons.util.BlankUtils;
import com.cndw.kungfu.config.Constants;
import com.cndw.kungfu.config.ConstantsModel;
import com.cndw.kungfu.config.ConstantsRadio;
import com.cndw.kungfu.domain.GoodsMode;
import com.cndw.kungfu.domain.Player;
import com.cndw.kungfu.domain.Scene;
import com.cndw.kungfu.domain.Union;
import com.cndw.kungfu.ext.LanguageLib;
import com.cndw.kungfu.ext.LogUtil;
import com.cndw.kungfu.ext.NumberProcesser;
import com.cndw.kungfu.ext.TimeProcesser;
import com.cndw.kungfu.model.ActivitySerialize;
import com.cndw.kungfu.model.Context;
import com.cndw.kungfu.model.battle.FighterMonster;
import com.cndw.kungfu.model.sys.ChatMain;
import com.cndw.kungfu.vo.EventNotice;

/**
 * 围城战对象
 * 
 * @author <a href="mailto:whz-work@163.com">汪洪州</a>
 * 
 * @since 1.0 Create on 2012-2-22
 */
public class SiegeWar {

	/**
	 * 开始时间
	 */
	private static int beginTime;

	/**
	 * 结束时间
	 */
	private static int endTime;

	/**
	 * 标志是否已经启动广播
	 */
	private static boolean isBroadcast = false;

	/**
	 * 当前障碍(拒马庄，城墙）
	 */
	private static FighterMonster currentMonster = null;

	/**
	 * 当前帮派战所在场景
	 */
	private static int currentScene = ConstantsModel.siegeScene[0];

	/**
	 * 进入第二场景时间
	 */
	private static int intoSecondSceneTime = 0;

	/**
	 * 进入围城场景的所有玩家
	 */
	private static final ConcurrentHashMap<Long, Boolean> joinPlayers = new ConcurrentHashMap<Long, Boolean>();

	/**
	 * 参与战斗的玩家列表
	 */
	private static final Map<Long, SiegePlayer> siegePlayers = new ConcurrentHashMap<Long, SiegePlayer>();

	/**
	 * 排行榜
	 */
	private static final Map<Integer, SiegeRanking> ranking = new ConcurrentHashMap<Integer, SiegeRanking>();

	/**
	 * 玩家奖励
	 */
	private static final Map<Long, SiegePlayerAwards> playerAwards = new ConcurrentHashMap<Long, SiegePlayerAwards>();
	/**
	 * 衰兵必败的buff
	 */
	private static int soldiersBuff = 0;

	/**
	 * 进入围城成员
	 * 
	 * @param playerId
	 */
	public static void addJoinPlayers(Player player) {
		joinPlayers.put(player.getPlayerId(), true);
		addPlayer(player);
	}

	/**
	 * 增加排行数据
	 * 
	 * @param player
	 */
	private static void addPlayer(Player player) {
		Union union = Context.getUnionServer().getUnionById(player.getUnionId());
		if (!BlankUtils.isBlank(union)) {
			synchronized (ranking) {
				if (ranking.containsKey(player.getUnionId())) {
					Map<Long, PlayerRanking> players = ranking.get(player.getUnionId()).getPlayers();
					if (!players.containsKey(player.getPlayerId())) {
						players.put(player.getPlayerId(), new PlayerRanking(player.getPlayerId(), player.getPlayerName()));
					}
				} else {
					SiegeRanking unionRanking = new SiegeRanking(union.getId(), union.getName());
					unionRanking.getPlayers().put(player.getPlayerId(), new PlayerRanking(player.getPlayerId(), player.getPlayerName()));
					ranking.put(player.getUnionId(), unionRanking);
				}
			}
		}
	}

	/**
	 * 获取玩家复活时间
	 * 
	 * @param playerId
	 * @return
	 */
	public static int[] getPlayerReviveInfo(Long playerId) {
		int[] result = new int[] { 0, 0, 0, 0, 0 };
		SiegePlayer player = getSiegePlayer(playerId);
		if (player != null) {
			result[0] = player.getReviveTime();
			result[1] = player.getReviveCount();
			result[2] = player.getBuffAdd();
			result[3] = player.getFatigue();
			result[4] = player.getBuffTimes();
		}
		return result;
	}

	public static SiegePlayer getSiegePlayer(long playerId) {
		return siegePlayers.get(playerId);
	}

	/**
	 * 获取未死亡的防守人员
	 * 
	 * @return
	 */
	public static List<SiegePlayer> getSiegeActivePlayers() {
		List<SiegePlayer> players = new ArrayList<SiegePlayer>();
		for (SiegePlayer player : siegePlayers.values()) {
			if (player.isActive()) {
				players.add(player);
			}
		}
		Collections.sort(players);
		return players;
	}

	/**
	 * 记录参加战斗的玩家
	 * 
	 * @param player
	 */
	public static boolean addSiegePlayers(Player player, boolean isAttack) {
		if (!joinPlayers.containsKey(player.getPlayerId())) {
			addPlayer(player);
		}
		if (!siegePlayers.containsKey(player.getPlayerId())) {
			siegePlayers.put(player.getPlayerId(), new SiegePlayer(player.getPlayerId(), player.getLevel(), player.getPlayerName(), isAttack));
		} else {
			SiegePlayer p = siegePlayers.get(player.getPlayerId());
			if (p.isDeath() || isAttack) {// 死亡状态或者攻击方
				return false;
			}
			p.setActive(!isAttack);
		}
		return !isAttack;
	}

	public static void addSiegeOnly(Player player) {
		if (player.getUnionId() == ActivitySerialize.getInstance().getSiegeUnionId()[0]) {
			SiegeWar.addSiegePlayers(player, false);
		} else {
			SiegeWar.addSiegePlayers(player, true);
		}
	}

	/**
	 * 判断是否在倒计时内
	 * 
	 * @return
	 */
	public static boolean isCountDownTime() {
		if (currentScene == ConstantsModel.siegeScene[0]) {
			return TimeProcesser.getUnixTime() < (beginTime + 60); // 外场景60秒倒计时
		} else {
			return TimeProcesser.getUnixTime() < (intoSecondSceneTime); // 内场景10秒倒计时
		}
	}

	/**
	 * 进入内场景
	 * 
	 * @return
	 */
	public static void intoSecondScene(int costTime) {
		LogUtil.getMain().info("siege into second scene ");
		intoSecondSceneTime = TimeProcesser.getUnixTime() + costTime + 60;
		currentScene = ConstantsModel.siegeScene[1];
		currentMonster = Context.getUndercityServer().getMonster(ConstantsModel.siegeMonster[1]).fighter();

		EventNotice notice = new EventNotice(ConstantsRadio.siege, ConstantsRadio.siegeIntoSecond);
		notice.put("sceneId", getCurrentScene());
		notice.put("hp", SiegeWar.getCurrentMonster().getHp());
		notice.put("maxHp", SiegeWar.getCurrentMonster().getMaxHp());
		notice.put("monsterId", SiegeWar.getCurrentMonster().getSourceObject().getId());
		notice.put("beginTime", intoSecondSceneTime);

		Scene scene = Context.getSceneServer().getSceneById(SiegeWar.getCurrentScene());
		Union union = Context.getUnionServer().getUnionById(ActivitySerialize.getInstance().getSiegeUnionId()[0]);

		for (Long playerId : joinPlayers.keySet()) {
			Player player = Context.getPlayerServer().getByPlayerId(playerId);
			if (!BlankUtils.isBlank(union) && union.getMemberIds().contains(player.getPlayerId())) {
				player.setTx(scene.getBirthPoint()[2] + NumberProcesser.mtRand(-150, -50));
				player.setTy(scene.getBirthPoint()[3] + NumberProcesser.mtRand(-100, 100));
			} else {
				player.setTx(scene.getBirthPoint()[0] + NumberProcesser.mtRand(150, 50));
				player.setTy(scene.getBirthPoint()[1] + NumberProcesser.mtRand(-100, 100));
			}
			player.setTs(1); // 是否传送
		}

		notice.broadcast(joinPlayers.keySet());
	}

	/**
	 * 计算积分
	 * 
	 * @param wine
	 * @param lose
	 */
	public static void clacScore(Player wine, Player lose) {
		try {
			SiegeRanking WinRanking = ranking.get(wine.getUnionId());
			WinRanking.alterScore(lose.getLevel());
			WinRanking.getPlayers().get(wine.getPlayerId()).alterScore(lose.getLevel());

			SiegeRanking loseRanking = ranking.get(lose.getUnionId());
			if (loseRanking != null) {
				loseRanking.alterScore(2);
				loseRanking.getPlayers().get(lose.getPlayerId()).alterScore(2);
				broadcastRanking(lose.getPlayerId());
			} else {
				LogUtil.getSystem().error("lost union lost ranking " + lose.getPlayerId() + " unionId:" + lose.getUnionId());
			}

		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	/**
	 * 计算积分
	 * 
	 * @param player
	 * @param sourceDam
	 */
	public static void clacScore(Player player, int sourceDam) {
		int score = Math.max(1, sourceDam / 100000);
		SiegeRanking unionRanking = ranking.get(player.getUnionId());
		if (unionRanking != null) {
			unionRanking.alterScore(score);
			unionRanking.getPlayers().get(player.getPlayerId()).alterScore(score);
			broadcastRanking(0);
		} else {
			LogUtil.getSysErr().error("no unionId " + player.getUnionId() + " id:" + player.getPlayerId());
		}

	}

	/**
	 * 广播新加入的防守
	 * 
	 * @param loseId
	 */
	public static void broadcastPlayer(Player player) {
		EventNotice notice = new EventNotice(ConstantsRadio.siege, ConstantsRadio.siegePlayers);
		notice.put("player", getSiegePlayer(player.getPlayerId()).toSiegePlayerVO());
		notice.broadcast(joinPlayers.keySet());
	}

	/**
	 * 广播排名
	 * 
	 * @param loseId
	 */
	public static void broadcastRanking(long loseId) {
		EventNotice notice = new EventNotice(ConstantsRadio.siege, ConstantsRadio.siegeRanking);
		notice.put("rank", getRanking(3));
		notice.put("loseId", loseId);
		notice.put("hp", getCurrentMonster().getHp());
		notice.put("maxHp", getCurrentMonster().getMaxHp());
		for (Long playerId : joinPlayers.keySet()) {
			Player player = Context.getPlayerServer().getByPlayerId(playerId);
			notice.put("myRank", getRanking().get(player.getUnionId()).clone());
			notice.put("unionRank", getRanking().get(player.getUnionId()).getPlayersVO());
			notice.broadcast(playerId);
		}

	}

	/**
	 * 获取攻方前几排名
	 * 
	 * @return
	 */
	public static List<SiegeRanking> getRanking(int rank) {
		int i = 0;
		List<SiegeRanking> siegeRanking = new ArrayList<SiegeRanking>();
		Set<SiegeRanking> rankings = new TreeSet<SiegeRanking>(ranking.values());

		if (rankings != null) {
			for (SiegeRanking r : rankings) {
				r.setRanking(i + 1);
				r.setPlayerRanking(); // 给帮派成员设置排名
				r = r.clone(); // 不需要帮派成员数据

				if (r.getId() == ActivitySerialize.getInstance().getSiegeUnionId()[0]) {
					continue;
				}

				i++;
				if (i <= rank) {
					siegeRanking.add(r);
				}
			}
		}

		return siegeRanking;
	}

	/**
	 * 广播战斗开始
	 */
	public static void addBroadcast() {

		beginTime = (TimeProcesser.getHourTime(ConstantsModel.siegeTime[1])); // 获取围城战斗开始时间
		endTime = (TimeProcesser.getHourTime(ConstantsModel.siegeTime[2])); // 获取围城战斗结束时间
		int currentTime = TimeProcesser.getUnixTime();
		if (endTime <= currentTime) { // 已结束
			beginTime += 86400;
			endTime += 86400;
		}

		Context.getTimerServer().scheduleAtFixedRate(new Runnable() {
			@Override
			public void run() {
				try {
					bossStart();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}, beginTime - currentTime, 86400);

		LogUtil.getMain().debug("siege init wait " + (beginTime - currentTime));
	}

	public static synchronized void bossStart() {
		if (isBroadcast) {
			return;
		}
		LogUtil.getMain().info("siege is start ...");
		isBroadcast = true;
		beginTime = TimeProcesser.getUnixTime();
		endTime = (TimeProcesser.getHourTime(ConstantsModel.siegeTime[2])); // 获取围城战斗结束时间
		// 清空上次的奖励
		playerAwards.clear();
		currentScene = ConstantsModel.siegeScene[0];

		// 初始化拒马庄
		currentMonster = Context.getUndercityServer().getMonster(ConstantsModel.siegeMonster[0]).fighter();

		// 防守帮派成员
		Union union = Context.getUnionServer().getUnionById(ActivitySerialize.getInstance().getSiegeUnionId()[0]);
		EventNotice notice = new EventNotice(ConstantsRadio.siege, ConstantsRadio.siegeBegin);
		if (!BlankUtils.isBlank(union)) {
			notice.put("unionName", union.getName());
		}
		notice.broadcast(Constants.COMMRADIO);

		try {
			int winTimes = ActivitySerialize.getInstance().getSiegeUnionId()[1];
			if (winTimes >= 2) {
				soldiersBuff = 10 * (winTimes - 2);
			} else {
				soldiersBuff = 0;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		Context.getTimerServer().scheduleSeconds(new Runnable() {
			@Override
			public void run() {
				closeWar(false); // 活动时间到，强制结束
			}
		}, endTime - TimeProcesser.getUnixTime());

	}

	/**
	 * 获取玩家奖励
	 * 
	 * @param isWine
	 *            攻城成功
	 * @param siegeRank
	 *            防守排名数据
	 * @param player
	 *            当前玩家
	 * @param unionId
	 *            防守帮派Id
	 * @return
	 */
	private static SiegePlayerAwards getAwords(boolean isWine, Player player, int unionId) {

		// 未加入战斗
		if (!siegePlayers.containsKey(player.getPlayerId())) {
			return null;
		}
		if (getPlayerScore(player) == 0) {
			return null;
		}

		SiegePlayerAwards awards = new SiegePlayerAwards();

		// 参与奖励
		awards.alterAsset(SiegeAwards.getValue(SiegeAwards.JOIN_A, player.getLevel()));
		awards.alterExp(SiegeAwards.getValue(SiegeAwards.JOIN_E, player.getLevel()));
		awards.alterResource(SiegeAwards.getValue(SiegeAwards.JOIN_C, player.getLevel()));
		awards.setGoods(getAwardGoods(SiegeAwards.JOIN_G, player.getLevel()));

		if (player.getUnionId() == unionId) {
			// 防守成功
			if (!isWine) {
				awards.alterAsset(SiegeAwards.getValue(SiegeAwards.WARD_A, player.getLevel()));
				awards.alterExp(SiegeAwards.getValue(SiegeAwards.WARD_E, player.getLevel()));
				awards.alterResource(SiegeAwards.getValue(SiegeAwards.WARD_C, player.getLevel()));

				// 守城成功的帮派，帮派个人积分前十者
				PlayerRanking playerRank = getRanking().get(unionId).getPlayers().get(player.getPlayerId());
				if (playerRank.getRanking() <= 10) {
					awards.getGoods().addAll(getAwardGoods(SiegeAwards.WARD_TOPTEN, player.getLevel()));
				}
			}
		} else {

			// 攻城排名前十
			if (player.getUnionId() != unionId && getRanking().get(player.getUnionId()).getRanking() <= 10) {
				awards.alterAsset(SiegeAwards.getValue(SiegeAwards.TOPTEN_A, player.getLevel()));
				awards.alterExp(SiegeAwards.getValue(SiegeAwards.TOPTEN_E, player.getLevel()));
				awards.alterResource(SiegeAwards.getValue(SiegeAwards.TOPTEN_C, player.getLevel()));
			}

			SiegeRanking sRank = getRanking().get(player.getUnionId());
			if (sRank.getRanking() == 1) { // 攻城帮派第一
				if (sRank.getPlayers().get(player.getPlayerId()).getRanking() <= 10) { // 帮派中前十
					awards.getGoods().addAll(getAwardGoods(SiegeAwards.FIRST_TOPTEN, player.getLevel()));
				}
			} else if (sRank.getRanking() == 2) {// 攻城帮派第二
				if (sRank.getPlayers().get(player.getPlayerId()).getRanking() <= 5) { // 帮派中前五
					awards.getGoods().addAll(getAwardGoods(SiegeAwards.SECOND_TOPFIFTH, player.getLevel()));
				}
			} else if (sRank.getRanking() == 3) {// 攻城帮派第三
				if (sRank.getPlayers().get(player.getPlayerId()).getRanking() <= 3) { // 帮派中前三
					awards.getGoods().addAll(getAwardGoods(SiegeAwards.THIRD_TOPTHIRD, player.getLevel()));
				}
			}
		}
		return awards;
	}

	/**
	 * 获取奖励的物品
	 * 
	 * @return
	 */
	private static List<Object[]> getAwardGoods(String awardType, long playerLevel) {
		List<Object[]> awardGoods = new ArrayList<Object[]>();
		SiegeAwards siegeAwards = SiegeAwards.get(awardType);
		List<Integer[]> goods = siegeAwards.getGoodsList();
		for (Integer[] g : goods) {
			awardGoods.add(new Object[] { g[1], g[0], Context.getGoodsServer().getModeById(g[0]).getName(), g[2] });
		}
		if (!BlankUtils.isBlank(siegeAwards.getOrangeBoxCount())) {
			String[] orange = siegeAwards.getOrangeBoxCount().split("\\*");
			GoodsMode mode = SiegeAwards.getOrangeBox(playerLevel);
			awardGoods.add(new Object[] { Integer.parseInt(orange[0]), mode.getGoodsId(), mode.getName(), Integer.parseInt(orange[1]) });
		}
		return awardGoods;
	}

	/**
	 * 围城活动结束，清理数据,统计结果，发送奖励
	 */
	public static synchronized void closeWar(boolean isWine) {
		if (isBroadcast == false) {// 已经处理过结束
			return;
		}
		LogUtil.getMain().info("siege is stop by win is " + isWine);
		try {
			// 获取前三排名数据
			List<SiegeRanking> siegeRank = getRanking(10);
			ActivitySerialize activitySerialize = ActivitySerialize.getInstance();
			int oldUnionId = ActivitySerialize.getInstance().getSiegeUnionId()[0];
			if (!siegeRank.isEmpty()) {

				// 获取前三的帮派名字
				StringBuilder sb = new StringBuilder();
				for (int i = 0, j = siegeRank.size() > 3 ? 3 : siegeRank.size(); i < j; i++) {
					sb.append(siegeRank.get(i).getName());
					sb.append("、");
				}
				if (sb.length() > 0) {
					sb.delete(sb.length() - 1, sb.length());
				}
				String winUnionName = null;
				if (oldUnionId == 0) { // 第一次围城，积分最高为下次守城
					activitySerialize.getSiegeUnionId()[1] = 0;
					activitySerialize.getSiegeUnionId()[0] = (int) siegeRank.get(0).getId();
					ChatMain.systemMessage(LanguageLib.get("siege.msg.wineSys", sb.toString(), siegeRank.get(0).getName()));
					winUnionName = siegeRank.get(0).getName();
				} else {
					// 是否攻城成功
					Union union = Context.getUnionServer().getUnionById(oldUnionId);

					if (isWine) {
						activitySerialize.getSiegeUnionId()[1] = 0;
						activitySerialize.getSiegeUnionId()[0] = (int) siegeRank.get(0).getId();
						if (union != null) {
							ChatMain.systemMessage(LanguageLib.get("siege.msg.wine", union.getName(), sb.toString(), siegeRank.get(0).getName()));
						}
						winUnionName = siegeRank.get(0).getName();
					} else {
						activitySerialize.getSiegeUnionId()[1] = activitySerialize.getSiegeUnionId()[1] + 1;
						if (union != null) {
							ChatMain.systemMessage(LanguageLib.get("siege.msg.lose", union.getName(), sb.toString(), union.getName()));
							winUnionName = union.getName();
						}
					}

				}

				// 结束广播
				EventNotice notice = new EventNotice(ConstantsRadio.siege, ConstantsRadio.siegeEnd);
				notice.put("isWine", isWine);
				notice.put("unionName", winUnionName);
				for (Long playerId : joinPlayers.keySet()) {
					Player player = Context.getPlayerServer().getByPlayerId(playerId);
					SiegePlayerAwards awards = getAwords(isWine, player, oldUnionId);
					if (awards != null) {
						playerAwards.put(playerId, awards);
						notice.put("awards", awards);
					} else {
						notice.put("awards", null);
					}

					notice.put("sceneId", player.getDataInfo().getLastSceneId());
					notice.broadcast(playerId);
				}

				// 将排行数据序列化
				activitySerialize.setSiegeRanking(siegeRank);
				activitySerialize.commitSync();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		isBroadcast = false;
		intoSecondSceneTime = 0;
		currentMonster = null;
		currentScene = ConstantsModel.siegeScene[0];
		ranking.clear();
		joinPlayers.clear();
		siegePlayers.clear();
	}

	/**
	 * 删除玩家
	 * 
	 * @param playerId
	 */
	public static void removePlayer(Long playerId) {
		joinPlayers.remove(playerId);
		siegePlayers.remove(playerId);
		EventNotice notice = new EventNotice(ConstantsRadio.siege, ConstantsRadio.siegeRemove);
		notice.put("playerId", playerId);
		if (!joinPlayers.isEmpty() && joinPlayers.containsKey(playerId)) {
			notice.broadcast(joinPlayers.keySet());
		}
	}

	public static void noPlayer(long playerId) {
		if (siegePlayers != null && siegePlayers.containsKey(playerId)) {
			siegePlayers.get(playerId).setActive(false);
		}
	}

	public static int getPlayerScore(Player player) {
		try {
			return ranking.get(player.getUnionId()).getPlayers().get(player.getPlayerId()).getScore();
		} catch (Exception e) {
			if (!ranking.containsKey(player.getUnionId())) {
				LogUtil.getSysErr().error("no unionId " + player.getUnionId() + " id:" + player.getPlayerId());
			} else {
				LogUtil.getSysErr().error("other " + player.getUnionId() + " id:" + player.getPlayerId());
			}
			e.printStackTrace();
		}
		return 0;
	}

	public static int getPlayerRanking(Player player) {
		try {
			return ranking.get(player.getUnionId()).getPlayers().get(player.getPlayerId()).getRanking();
		} catch (Exception e) {
			if (!ranking.containsKey(player.getUnionId())) {
				LogUtil.getSysErr().error("no unionId " + player.getUnionId() + " id:" + player.getPlayerId());
			} else {
				LogUtil.getSysErr().error("other " + player.getUnionId() + " id:" + player.getPlayerId());
			}
			e.printStackTrace();
		}
		return 0;
	}

	public static int getCurrentScene() {
		return currentScene;
	}

	public static FighterMonster getCurrentMonster() {
		return currentMonster;
	}

	public static Map<Integer, SiegeRanking> getRanking() {
		return ranking;
	}

	public static int getBeginTime() {
		return beginTime;
	}

	public static int getEndTime() {
		return endTime;
	}

	public static int getIntoSecondSceneTime() {
		return intoSecondSceneTime;
	}

	public static Map<Long, SiegePlayerAwards> getPlayerawards() {
		return playerAwards;
	}

	public static boolean isBroadcast() {
		return isBroadcast;
	}

	public static int getSoldiersBuff() {
		return soldiersBuff;
	}

}
